/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import 'dart:math';
import 'dart:async';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:hadss_uni_input/src/keyboard_detector.dart';
import 'package:hadss_uni_input/src/gesture_utils.dart';
import 'package:hadss_uni_input/src/touch_finger.dart';

import '../hadss_uni_input.dart';
import 'package:vector_math/vector_math.dart' as vector;

/// 鼠标滚轮，滚动结束的判断时间，毫秒
const mouseWheelEndMilliSecond = 300;

/// 长按判断时间，毫秒
const longPressTimerMilliSecond = 500;

/// 触发轻扫的最慢速度
const swipeSpeedDpS = 100.0;

/// 触发滚动的最小距离
const panDistanceDp = 5.0;

/// 触发缩放的最小距离
const pinchDistanceDp = 5.0;

/// 触发缩放的最小距离
const angleDeg = 1.0;

/// 触摸板缩放阈值
const touchPadOffsetScale = 0.05;

class UnifiedGestureDetector extends StatefulWidget {
  /// Creates a widget that detects gestures.
  const UnifiedGestureDetector(
      {super.key,
        required this.child,
        this.pointerOptions,
        this.onPanStart,
        this.onPanUpdate,
        this.onPanEnd,
        this.onPanCancel,
        this.onPinchStart,
        this.onPinchUpdate,
        this.onPinchEnd,
        this.onPinchCancel,
        this.onSwipe,
        this.onRotateStart,
        this.onRotateUpdate,
        this.onRotateEnd,
        this.onRotateCancel,
        this.onContentMenu,
        this.onHover,
        this.onDoubleTap,
        this.onDoubleTapDown,
        this.onDoubleTapCancel,
        this.onLongPress,
        this.onLongPressStart,
        this.onLongPressDown,
        this.onLongPressMoveUpdate,
        this.onLongPressUp,
        this.onLongPressEnd,
        this.onLongPressCancel,
        this.onTap,
        this.onTapDown,
        this.onTapUp,
        this.onTapCancel,
        this.onDragDown,
        this.onDragStart,
        this.onDragUpdate,
        this.onDragEnd,
        this.onDragCancel});

  final Widget child;

  /// 配置参数
  final PointerOptions? pointerOptions;

  /// 滚动/平移开始
  final Function(GestureEvent event)? onPanStart;

  /// 滚动/平移中
  final Function(GestureEvent event)? onPanUpdate;

  /// 滚动/平移结束
  final Function(GestureEvent event)? onPanEnd;

  /// 滚动/平移取消
  final Function(GestureEvent event)? onPanCancel;

  /// 缩放开始
  final Function(GestureEvent event)? onPinchStart;

  /// 缩放中
  final Function(GestureEvent event)? onPinchUpdate;

  /// 缩放结束
  final Function(GestureEvent event)? onPinchEnd;

  /// 缩放取消
  final Function(GestureEvent event)? onPinchCancel;

  /// 轻扫
  final Function(GestureEvent event)? onSwipe;

  /// 旋转开始
  final Function(GestureEvent event)? onRotateStart;

  /// 旋转中
  final Function(GestureEvent event)? onRotateUpdate;

  /// 旋转结束
  final Function(GestureEvent event)? onRotateEnd;

  /// 旋转取消
  final Function(GestureEvent event)? onRotateCancel;

  /// 上下文菜单
  final Function(GestureEvent event)? onContentMenu;

  /// 悬浮
  final Function(bool isHover, PointerEvent event)? onHover;

  /// 双击
  final Function()? onDoubleTap;

  /// 双击按下
  final Function(TapDownDetails detail)? onDoubleTapDown;

  /// 双击取消
  final Function()? onDoubleTapCancel;

  /// 长按
  final Function()? onLongPress;

  /// 长按开始
  final Function(LongPressStartDetails detail)? onLongPressStart;

  /// 长按按下
  final Function(LongPressDownDetails detail)? onLongPressDown;

  /// 长按移动进行中
  final Function(LongPressMoveUpdateDetails detail)? onLongPressMoveUpdate;

  /// 长按进行中
  final Function()? onLongPressUp;

  /// 长按结束
  final Function(LongPressEndDetails detail)? onLongPressEnd;

  /// 长按取消
  final Function()? onLongPressCancel;

  /// 点击
  final Function()? onTap;

  /// 点击按下
  final Function(TapDownDetails detail)? onTapDown;

  /// 点击弹起
  final Function(TapUpDetails detail)? onTapUp;

  /// 点击取消
  final Function()? onTapCancel;

  /// 推拽按下
  final Function(DragDownDetails detail)? onDragDown;

  /// 拖拽开始
  final Function(DragStartDetails detail)? onDragStart;

  /// 拖拽进行中
  final Function(DragUpdateDetails detail)? onDragUpdate;

  /// 拖拽结束
  final Function(DragEndDetails detail)? onDragEnd;

  /// 拖拽取消
  final Function()? onDragCancel;

  @override
  UnifiedGestureDetectorState createState() {
    return UnifiedGestureDetectorState();
  }
}

enum _MouseWheelState { start, update, unknown }

class UnifiedGestureDetectorState extends State<UnifiedGestureDetector> {
  final List<TouchFinger> _touches = []; // 保存当前按住的手指触
  double _initialPinchDistance = 1.0;
  bool _isControlPressed = false;
  bool _isShiftPressed = false;
  int _pressedKeysLength = 0;
  GestureState _state = GestureState.unknown;
  GestureState _panState = GestureState.unknown;
  GestureState _pinchState = GestureState.unknown;
  GestureState _rotateState = GestureState.unknown;
  late PointerOptions _options;
  Timer? _longPressTimer;
  Timer? _scrollEndTimer;
  _MouseWheelState _mouseWheelState = _MouseWheelState.unknown;
  DateTime _mouseWheelStartTime = DateTime.now();

  // 针对触控板
  Offset _startOffset = const Offset(0, 0);
  Offset _updateOffset = const Offset(0, 0);
  DateTime _startTime = DateTime.now();

  @override
  void initState() {
    super.initState();

    _options = widget.pointerOptions ?? const PointerOptions();
  }

  @override
  void dispose() {
    if (_scrollEndTimer != null) {
      _scrollEndTimer!.cancel();
      _scrollEndTimer = null;
    }
    if (_longPressTimer != null) {
      _longPressTimer!.cancel();
      _longPressTimer = null;
    }
    onCancelHandler();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Listener(
        onPointerDown: onPointerDown,
        onPointerMove: onPointerMove,
        onPointerUp: onPointerUp,
        onPointerSignal: onPointerSignal,
        onPointerPanZoomStart: onPointerPanZoomStart,
        onPointerPanZoomUpdate: onPointerPanZoomUpdate,
        onPointerPanZoomEnd: onPointerPanZoomEnd,
        child: KeyboardDetector(
          onControlPress: (bool isPressed, int pressedKeysLength) {
            _isControlPressed = isPressed;
            _pressedKeysLength = pressedKeysLength;
          },
          onShiftPress: (bool isPressed, int pressedKeysLength) {
            _isShiftPressed = isPressed;
            _pressedKeysLength = pressedKeysLength;
          },
          child: GestureDetector(
            onDoubleTap: () {
              if (widget.onDoubleTap != null) {
                widget.onDoubleTap!();
              }
            },
            onDoubleTapDown: (detail) {
              if (widget.onDoubleTapDown != null) {
                widget.onDoubleTapDown!(detail);
              }
            },
            onDoubleTapCancel: () {
              if (widget.onDoubleTapCancel != null) {
                widget.onDoubleTapCancel!();
              }
            },
            onLongPress: () {
              if (widget.onLongPress != null) {
                widget.onLongPress!();
              }
            },
            onLongPressStart: (detail) {
              if (widget.onLongPressStart != null) {
                widget.onLongPressStart!(detail);
              }
            },
            onLongPressDown: (detail) {
              if (widget.onLongPressDown != null) {
                widget.onLongPressDown!(detail);
              }
            },
            onLongPressMoveUpdate: (detail) {
              if (widget.onLongPressMoveUpdate != null) {
                widget.onLongPressMoveUpdate!(detail);
              }
            },
            onLongPressUp: () {
              if (widget.onLongPressUp != null) {
                widget.onLongPressUp!();
              }
            },
            onLongPressEnd: (detail) {
              if (widget.onLongPressEnd != null) {
                widget.onLongPressEnd!(detail);
              }
            },
            onLongPressCancel: () {
              if (widget.onLongPressCancel != null) {
                widget.onLongPressCancel!();
              }
            },
            onTap: () {
              if (widget.onTap != null) {
                widget.onTap!();
              }
            },
            onTapDown: (detail) {
              if (widget.onTapDown != null) {
                widget.onTapDown!(detail);
              }
            },
            onTapUp: (detail) {
              if (widget.onTapUp != null) {
                widget.onTapUp!(detail);
              }
            },
            onTapCancel: () {
              if (widget.onTapCancel != null) {
                widget.onTapCancel!();
              }
            },
            onHorizontalDragDown: (detail) {
              if (widget.onDragDown != null) {
                widget.onDragDown!(detail);
              }
            },
            onHorizontalDragStart: (detail) {
              if (widget.onDragStart != null) {
                widget.onDragStart!(detail);
              }
            },
            onHorizontalDragUpdate: (detail) {
              if (widget.onDragUpdate != null) {
                widget.onDragUpdate!(detail);
              }
            },
            onHorizontalDragEnd: (detail) {
              if (widget.onDragEnd != null) {
                widget.onDragEnd!(detail);
              }
            },
            onHorizontalDragCancel: () {
              if (widget.onDragCancel != null) {
                widget.onDragCancel!();
              }
            },
            onVerticalDragDown: (detail) {
              if (widget.onDragDown != null) {
                widget.onDragDown!(detail);
              }
            },
            onVerticalDragStart: (detail) {
              if (widget.onDragStart != null) {
                widget.onDragStart!(detail);
              }
            },
            onVerticalDragUpdate: (detail) {
              if (widget.onDragUpdate != null) {
                widget.onDragUpdate!(detail);
              }
            },
            onVerticalDragEnd: (detail) {
              if (widget.onDragEnd != null) {
                widget.onDragEnd!(detail);
              }
            },
            onVerticalDragCancel: () {
              if (widget.onDragCancel != null) {
                widget.onDragCancel!();
              }
            },
            child: MouseRegion(
              onEnter: (event) {
                if (widget.onHover != null) {
                  widget.onHover!(true, event);
                }
              },
              onExit: (event) {
                if (widget.onHover != null) {
                  widget.onHover!(false, event);
                }
              },
              child: widget.child,
            ),
          ),
        ));
  }

  /// 鼠标滚轮
  void onPointerSignal(PointerSignalEvent event) {
    if (event is PointerScrollEvent) {
      // 用户开始/正在滚动
      if (_mouseWheelState == _MouseWheelState.unknown) {
        _mouseWheelStartTime = DateTime.now();
        setState(() {
          _mouseWheelState = _MouseWheelState.start;
        });
      } else {
        setState(() {
          _mouseWheelState = _MouseWheelState.update;
        });
      }

      checkScrollEndTimer(event);

      if (_isControlPressed) {
        // 本组件所有手势，键盘不允许同时按下两个键
        if (_pressedKeysLength > 1) {
          return;
        }
        // 回调缩放
        if (widget.onPinchStart != null &&
            _mouseWheelState == _MouseWheelState.start) {
          widget.onPinchStart!(GestureEvent(
              pinchCenterX: event.position.dx,
              pinchCenterY: event.position.dy,
              scale: event.scrollDelta.dy));
        } else if (widget.onPinchUpdate != null &&
            _mouseWheelState == _MouseWheelState.update) {
          widget.onPinchUpdate!(GestureEvent(
              pinchCenterX: event.position.dx,
              pinchCenterY: event.position.dy,
              scale: event.scrollDelta.dy));
        }
      } else if (_isShiftPressed) {
        // 本组件所有手势，键盘不允许同时按下两个键
        if (_pressedKeysLength > 1) {
          return;
        }
        // 回调左右平移
        onMousePanHandle(event, event.scrollDelta.dy, event.scrollDelta.dx,
            _mouseWheelStartTime);
      } else {
        // 回调上下滚动
        onMousePanHandle(event, event.scrollDelta.dx, event.scrollDelta.dy,
            _mouseWheelStartTime);
      }
    }
  }

  void checkScrollEndTimer(PointerScrollEvent event) {
    // 取消之前的计时器
    _scrollEndTimer?.cancel();

    // 设置新的计时器，300ms后认为滚动结束
    _scrollEndTimer =
        Timer(const Duration(milliseconds: mouseWheelEndMilliSecond), () {
          setState(() {
            _mouseWheelState = _MouseWheelState.unknown;
            if (_isControlPressed && widget.onPinchEnd != null) {
              widget.onPinchEnd!(GestureEvent(
                  pinchCenterX: event.position.dx,
                  pinchCenterY: event.position.dy,
                  scale: event.scrollDelta.dy));
            } else if (_isShiftPressed && widget.onPanEnd != null) {
              widget.onPanEnd!(GestureEvent(
                  offsetX: event.scrollDelta.dy, offsetY: event.scrollDelta.dx));
            } else if (widget.onPanEnd != null) {
              widget.onPanEnd!(GestureEvent(
                  offsetX: event.scrollDelta.dx, offsetY: event.scrollDelta.dy));
            }
          });
        });
  }

  void onMousePanHandle(PointerScrollEvent event, double offsetX,
      double offsetY, DateTime startTime) {
    double xSpeed = calculateSpeed(startTime, offsetX);
    double ySpeed = calculateSpeed(startTime, offsetY);
    final disPoint = sqrt(offsetX * offsetX + offsetY * offsetY);
    double speed = calculateSpeed(startTime, disPoint);
    if (widget.onPanStart != null &&
        _mouseWheelState == _MouseWheelState.start) {
      widget.onPanStart!(GestureEvent(
          offsetX: offsetX,
          offsetY: offsetY,
          velocityX: xSpeed,
          velocityY: ySpeed,
          velocity: speed));
    } else if (widget.onPanUpdate != null &&
        _mouseWheelState == _MouseWheelState.update) {
      widget.onPanUpdate!(GestureEvent(
          offsetX: offsetX,
          offsetY: offsetY,
          velocityX: xSpeed,
          velocityY: ySpeed,
          velocity: speed));
    }
  }

  /// 手指触按压
  void onPointerDown(PointerDownEvent event) {
    // 添加手指触
    _touches
        .add(TouchFinger(event.pointer, event.localPosition, DateTime.now()));
    if (touchCount == 1) {
      _state = GestureState.pointerDown;
      startContentMenu(event);
    } else if (touchCount == 2) {
      // 按下了2个手指，就是缩放和旋转的开始
      if (_options.enablePinch && _pinchState == GestureState.unknown) {
        _pinchState = GestureState.pinchStart;
      }
      if (_options.enableRotate && _rotateState == GestureState.unknown) {
        _rotateState = GestureState.rotateStart;
      }
    }
  }

  /// 手指触移动
  void onPointerMove(PointerMoveEvent event) {
    final touch = _touches.firstWhere((touch) => touch.id == event.pointer);
    touch.currentOffset = event.localPosition;
    if (_state == GestureState.pointerDown) {
      touch.startOffset = touch.currentOffset;
      touch.downTime = DateTime.now();
      _state = GestureState.unknown;
    }

    if (_panState == GestureState.unknown) {
      _panState = GestureState.panStart;
    }

    if (_panState == GestureState.panStart ||
        _panState == GestureState.panUpdate) {
      onPanHandler(touch.startOffset, touch.currentOffset, touch.downTime);
    }

    if (_pinchState == GestureState.pinchStart ||
        _pinchState == GestureState.pinchUpdate) {
      onPinchHandler(event, touch);
    }
    if (_rotateState == GestureState.rotateStart ||
        _rotateState == GestureState.rotateUpdate) {
      onRotateHandler(event, touch);
    }
  }

  /// 手指触抬起
  void onPointerUp(PointerEvent event) {
    final touch = _touches.firstWhere((touch) => touch.id == event.pointer);
    // 处理轻扫
    onSwipeHandler(touch.startOffset, touch.currentOffset, touch.downTime);

    // 移除对应的手指触
    _touches.removeWhere((touch) => touch.id == event.pointer);

    // 处理滚动
    if (_panState == GestureState.panStart) {
      _panState = GestureState.unknown;
    } else if (_panState == GestureState.panUpdate) {
      _panState = GestureState.unknown;
      widget.onPanEnd?.call(GestureEvent());
    }
    // 处理缩放
    if (_pinchState == GestureState.pinchStart) {
      _pinchState = GestureState.unknown;
    } else if (_pinchState == GestureState.pinchUpdate) {
      _pinchState = GestureState.unknown;
      widget.onPinchEnd?.call(GestureEvent());
    } else if (_pinchState == GestureState.unknown && touchCount == 2) {
      _pinchState = GestureState.pinchStart;
    }
    // 处理旋转
    if (_rotateState == GestureState.rotateStart) {
      _rotateState = GestureState.unknown;
    } else if (_rotateState == GestureState.rotateUpdate) {
      _rotateState = GestureState.unknown;
      widget.onRotateEnd?.call(GestureEvent());
    } else if (_rotateState == GestureState.unknown && touchCount == 2) {
      _rotateState = GestureState.rotateStart;
    }
  }

  /// 触控板开始
  void onPointerPanZoomStart(PointerPanZoomStartEvent event) {
    _startOffset = event.delta;
    _startTime = DateTime.now();
    _panState = GestureState.panStart;
    _pinchState = GestureState.pinchStart;
    _rotateState = GestureState.rotateStart;
  }

  /// 触控板过程
  void onPointerPanZoomUpdate(PointerPanZoomUpdateEvent event) {
    _updateOffset = event.localPan;
    onPanHandler(_updateOffset, _startOffset, _startTime);
    onTouchPadPinchHandler(event.scale);
    onTouchPadRotateHandler(event.rotation);
  }

  /// 触控板结束
  void onPointerPanZoomEnd(PointerPanZoomEndEvent event) {
    _panState = GestureState.unknown;
    _pinchState = GestureState.unknown;
    _rotateState = GestureState.unknown;
    onSwipeHandler(_updateOffset, _startOffset, _startTime);
    widget.onPanEnd?.call(GestureEvent());
    widget.onPinchEnd?.call(GestureEvent());
    widget.onRotateEnd?.call(GestureEvent());
  }

  /// 计算缩放、旋转 初始的2指间距离
  void initPinchAndRotate() {
    if (touchCount < 2) return;
    _initialPinchDistance =
        (_touches[0].currentOffset - _touches[1].currentOffset).distance;
  }

  /// 处理轻扫
  void onSwipeHandler(
      Offset startOffset, Offset currentOffset, DateTime startTime) {
    if (!_options.enableSwipe) return;
    // 轻扫最小速度 100dp/s 当滑动速度的值小于等于0时，会被转化为默认值。
    final minSpeed =
    _options.speed > 0 ? _options.speed : const PointerOptions().speed;

    final dx = currentOffset.dx - startOffset.dx;
    final dy = currentOffset.dy - startOffset.dy;
    SwipeDirection nowDirection;
    if (dx.abs() > dy.abs()) {
      // 横向
      nowDirection = SwipeDirection.horizontal;
    } else {
      // 竖向
      nowDirection = SwipeDirection.vertical;
    }
    // 计算手势直线距离
    final disPoint = sqrt(dx * dx + dy * dy);
    final endTime = DateTime.now();
    // 计算时间差
    Duration difference = endTime.difference(startTime);
    // 获取毫秒数
    int milliseconds = difference.inMilliseconds;
    final speed = disPoint / milliseconds;
    if (speed * 1000 < minSpeed) {
      return;
    }
    double angle = vector.degrees(atan2(currentOffset.dy - startOffset.dy,
        currentOffset.dx - startOffset.dx)) %
        360;
    if (angle < -180.0) angle += 360.0;
    if (angle > 180.0) angle -= 360.0;

    doSwipe(angle, nowDirection, speed);
  }

  void doSwipe(double angle, SwipeDirection nowDirection, double speed) {
    double rotation = vector.radians(angle);
    if (_options.direction == SwipeDirection.none) {
      return;
    }
    bool isSwipe = _options.direction == SwipeDirection.all ||
        (_options.direction == SwipeDirection.horizontal &&
            nowDirection == SwipeDirection.horizontal) ||
        (_options.direction == SwipeDirection.vertical &&
            nowDirection == SwipeDirection.vertical);
    if (isSwipe) {
      widget.onSwipe?.call(GestureEvent(speed: speed * 1000, angle: rotation));
    }
  }

  /// 处理滚动/平移
  void onPanHandler(
      Offset startOffset, Offset currentOffset, DateTime startTime) {
    if (!_options.enablePan) return;
    // 当设定的值小于0时，按默认值5处理。
    final minDis = _options.distance < 0
        ? const PointerOptions().distance
        : _options.distance;
    final dx = currentOffset.dx - startOffset.dx;
    final dy = currentOffset.dy - startOffset.dy;
    PanDirection nowDirection;
    if (dx.abs() > dy.abs()) {
      // 横向
      nowDirection = PanDirection.horizontal;
      nowDirection = dx > 0 ? PanDirection.right : PanDirection.left;
    } else {
      // 竖向
      nowDirection = PanDirection.vertical;
      nowDirection = dy > 0 ? PanDirection.down : PanDirection.up;
    }
    // 计算手势直线距离
    final disPoint = sqrt(dx * dx + dy * dy);

    // 如果传入的 当前方向不在设置的方向内，返回，不处理
    if (!const PointerOptions()
        .hasPanDirection(_options.panDirection, nowDirection)) {
      return;
    }
    double xSpeed = calculateSpeed(startTime, dx);
    double ySpeed = calculateSpeed(startTime, dy);
    double speed = calculateSpeed(startTime, disPoint);
    if (disPoint >= minDis && _panState == GestureState.panStart) {
      _panState = GestureState.panUpdate;
      widget.onPanStart?.call(GestureEvent(
          offsetX: dx,
          offsetY: dy,
          velocityX: xSpeed,
          velocityY: ySpeed,
          velocity: speed));
    }
    if (_panState == GestureState.panUpdate) {
      widget.onPanUpdate?.call(GestureEvent(
          offsetX: dx,
          offsetY: dy,
          velocityX: xSpeed,
          velocityY: ySpeed,
          velocity: speed));
    }
  }

  /// 处理缩放
  void onPinchHandler(PointerMoveEvent event, TouchFinger touch) {
    if (touchCount < 2) return;
    // 取值范围：[0, +∞)，当识别距离的值小于等于0时，会被转化为默认值。
    final minDis =
    _options.pinchDistance > 0 ? _options.pinchDistance : pinchDistanceDp;
    // 缩放
    final newDistance =
        (_touches[0].currentOffset - _touches[1].currentOffset).distance;
    final centerOffset =
        (_touches[0].currentOffset + _touches[1].currentOffset) / 2;
    final pinchDistance = newDistance - _initialPinchDistance;
    if (_pinchState == GestureState.pinchStart) {
      initPinchAndRotate();

      if (widget.onPinchStart != null && pinchDistance.abs() >= minDis) {
        // 双指捏合达到阈值触发缩放开始
        final centerOffset =
            (_touches[0].currentOffset + _touches[1].currentOffset) / 2;
        widget.onPinchStart!(GestureEvent(
            pinchCenterX: centerOffset.dx,
            pinchCenterY: centerOffset.dy,
            scale: 1));
        _pinchState = GestureState.pinchUpdate;
      }
    } else if (_pinchState == GestureState.pinchUpdate &&
        widget.onPinchUpdate != null &&
        pinchDistance.abs() >= minDis) {
      initPinchAndRotate();

      // 双指继续，缩放进行中
      widget.onPinchUpdate!(GestureEvent(
          pinchCenterX: centerOffset.dx,
          pinchCenterY: centerOffset.dy,
          scale: pinchDistance));
    }
  }

  /// 处理触摸板缩放
  void onTouchPadPinchHandler(double scale) {
    // 取值范围：[0, +∞)，当识别距离的值小于等于0时，会被转化为默认值。
    const centerOffset = Offset(0, 0);
    final offsetScale = scale - 1;
    if (_pinchState == GestureState.pinchStart) {
      if (widget.onPinchStart != null &&
          offsetScale.abs() >= touchPadOffsetScale) {
        // 双指捏合达到阈值触发缩放开始
        widget.onPinchStart!(GestureEvent(
            pinchCenterX: centerOffset.dx,
            pinchCenterY: centerOffset.dy,
            scale: offsetScale));
        _pinchState = GestureState.pinchUpdate;
      }
    } else if (_pinchState == GestureState.pinchUpdate &&
        widget.onPinchUpdate != null) {
      // 双指继续，缩放进行中
      widget.onPinchUpdate!(GestureEvent(
          pinchCenterX: centerOffset.dx,
          pinchCenterY: centerOffset.dy,
          scale: offsetScale));
    }
  }

  /// 处理旋转
  void onRotateHandler(PointerMoveEvent event, TouchFinger touch) {
    if (touchCount < 2) return;
    var angle = angleBetweenLines(_touches[0], _touches[1]);
    var rotate = vector.radians(angle);
    // 当改变度数的值小于等于0或大于360时，会被转化为默认值。
    final minAngle = (_options.angle > 0 && _options.angle <= 360)
        ? _options.angle
        : const PointerOptions().angle;
    if (_rotateState == GestureState.rotateStart) {
      initPinchAndRotate();

      if (angle.abs() >= minAngle && widget.onRotateStart != null) {
        // 达到阈值，视为旋转开始
        widget.onRotateStart!(GestureEvent(angle: -rotate));
        _rotateState = GestureState.rotateUpdate;
      }
    } else if (_rotateState == GestureState.rotateUpdate &&
        widget.onRotateUpdate != null) {
      // 双指继续，旋转进行中
      widget.onRotateUpdate!(GestureEvent(angle: -rotate));
    }
  }

  /// 处理触控板旋转
  void onTouchPadRotateHandler(double rotate) {
    // 当改变度数的值小于等于0或大于360时，会被转化为默认值。
    final minAngle = (_options.angle > 0 && _options.angle <= 360)
        ? _options.angle
        : const PointerOptions().angle;
    final minRotate = vector.radians(minAngle).abs();
    if (_rotateState == GestureState.rotateStart) {
      if (rotate >= minRotate && widget.onRotateStart != null) {
        // 达到阈值，视为旋转开始
        widget.onRotateStart!(GestureEvent(angle: rotate));
        _rotateState = GestureState.rotateUpdate;
      }
    } else if (_rotateState == GestureState.rotateUpdate &&
        widget.onRotateUpdate != null) {
      // 双指继续，旋转进行中
      widget.onRotateUpdate!(GestureEvent(angle: rotate));
    }
  }

  bool inLongPressRange(TouchFinger touch) {
    return (touch.currentOffset - touch.startOffset).distanceSquared < 25;
  }

  /// 处理上下文菜单
  void startContentMenu(PointerDownEvent event) {
    if (widget.onContentMenu != null) {
      if ((event.buttons == kPrimaryMouseButton ||
          event.buttons == kMiddleMouseButton) &&
          event.kind == PointerDeviceKind.mouse) {
        // 鼠标左键和中键，不触发菜单
        return;
      }
      if (event.buttons == kSecondaryMouseButton) {
        // 鼠标右键，直接回调上下文菜单
        _state = GestureState.contentMenu;
        onContentMenuHandler(event);
      } else {
        // 长按触发上下文菜单
        _longPressTimer =
            Timer(const Duration(milliseconds: longPressTimerMilliSecond), () {
              if (touchCount == 1 &&
                  _touches[0].id == event.pointer &&
                  inLongPressRange(_touches[0])) {
                _state = GestureState.contentMenu;
                onContentMenuHandler(event);
                _touches.removeWhere((touch) => touch.id == event.pointer);
                cleanupTimer();
              }
            });
      }
    }
  }

  /// 处理上下文菜单
  void onContentMenuHandler(PointerDownEvent event) {
    widget.onContentMenu!(GestureEvent(localPosition: event.localPosition));
  }

  void cleanupTimer() {
    if (_longPressTimer != null) {
      _longPressTimer!.cancel();
      _longPressTimer = null;
    }
  }

  /// 页面突然关闭，处理cancel逻辑
  void onCancelHandler() {
    if ((_panState == GestureState.panStart ||
        _panState == GestureState.panUpdate) &&
        widget.onPanCancel != null) {
      widget.onPanCancel!.call(GestureEvent());
    } else if ((_pinchState == GestureState.pinchStart ||
        _pinchState == GestureState.pinchUpdate) &&
        widget.onPinchCancel != null) {
      widget.onPinchCancel!.call(GestureEvent());
    } else if ((_rotateState == GestureState.rotateStart ||
        _rotateState == GestureState.rotateUpdate) &&
        widget.onRotateCancel != null) {
      widget.onRotateCancel!.call(GestureEvent());
    }
  }

  get touchCount => _touches.length;
}
